﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.IO;

using ZedGraph; 

namespace TimeSeriesForecastingDemo
{
    public partial class frmForecastDemo : Form
    {
       
        private double[] data = null;
        private double[,] dataToShow = null;

        private System.Windows.Forms.OpenFileDialog openFileDialog;
        
        public frmForecastDemo()
        {
            InitializeComponent();
        }

        private void updateMeasurements(ForecastTable dt)
        {
            if (dt == null) return;

            tbMeanSignedDeviaiton.Text = TimeSeries.MeanSignedError(dt, false, TimeSeries.DEFAULT_IGNORE).ToString();
            tbMeanAbsoluteDeviation.Text = TimeSeries.MeanAbsoluteError(dt, false, TimeSeries.DEFAULT_IGNORE).ToString();
            tbMeanAPError.Text= TimeSeries.MeanAbsolutePercentError(dt, false, TimeSeries.DEFAULT_IGNORE).ToString();
            tbMeanPercentError.Text=TimeSeries.MeanPercentError(dt, false, TimeSeries.DEFAULT_IGNORE).ToString();
            tbMeanSquaredError.Text= TimeSeries.MeanSquaredError(dt, false, TimeSeries.DEFAULT_IGNORE, 0).ToString();
            tbTrackingSignal.Text= TimeSeries.TrackingSignal(dt, false, TimeSeries.DEFAULT_IGNORE).ToString();
        }

        private void updateGraph(ForecastTable dt)
        {
            if (dt == null) return;
            
            // This is to remove all plots
            zedPreditionGraph.GraphPane.CurveList.Clear();

            // GraphPane object holds one or more Curve objects (or plots)
            GraphPane myPane = zedPreditionGraph.GraphPane;

            //// PointPairList holds the data for plotting, X and Y arrays 

            double x, y1, y2;
            PointPairList list1 = new PointPairList();
            PointPairList list2 = new PointPairList();

            for (int i = 0; i < data.Length; i++)
            {
                x = Convert.ToDouble(grdResults.Rows[i].Cells["ID"].FormattedValue.ToString());
                y1 = Convert.ToDouble(grdResults.Rows[i].Cells["Real"].FormattedValue.ToString());
                list1.Add(x, y1);
            }

            for (int i = 0; i < grdResults.Rows.Count; i++)
            {
                x = Convert.ToDouble(grdResults.Rows[i].Cells["ID"].FormattedValue.ToString());
                y2 = Convert.ToDouble(grdResults.Rows[i].Cells["Forecast"].FormattedValue.ToString());
                list2.Add(x, y2);
            }

            // Add cruves to myPane object
            LineItem myCurve1 = myPane.AddCurve("Real Data", list1, Color.Blue, SymbolType.Diamond);
            LineItem myCurve2 = myPane.AddCurve("Predition Value", list2, Color.Red, SymbolType.Circle);

            myCurve1.Line.Width = 2.0F;
            myCurve2.Line.Width = 2.0F;
            myPane.Title.Text = "Time Series Predition";
            myPane.XAxis.Title.Text = "Time";
            myPane.YAxis.Title.Text = "Value";

            // I add all three functions just to be sure it refeshes the plot.   
            zedPreditionGraph.AxisChange();
            zedPreditionGraph.Invalidate();
            zedPreditionGraph.Refresh();
        }

        //Transforms Textbox1 CSV into a decimal array
        private Decimal[] GetInput()
        {
            //String[] arrStr = inputList.ToString().Split(",".ToArray());
            Decimal[] arrDec = new Decimal[data.Length];

            for (Int32 i = 0; i < arrDec.Length; i++)
            {
                arrDec[i] = Decimal.Parse(data[i].ToString());
            }

            return arrDec;
        }

        private void sToolStripMenuItem_Click(object sender, EventArgs e)
        {
            grdResults.Columns.Clear();

            ForecastTable dt = TimeSeries.simpleMovingAverage(GetInput(), 5, 3, 0);
            grdResults.DataSource = dt;

            updateMeasurements(dt);
            updateGraph(dt);
        }

        private void naiveToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            grdResults.Columns.Clear();

            ForecastTable dt = TimeSeries.naive(GetInput(), 5, 0);
            grdResults.DataSource = dt;

            updateMeasurements(dt);
            updateGraph(dt);
        }

        private void wMAToolStripMenuItem_Click(object sender, EventArgs e)
        {
            grdResults.Columns.Clear();
            
            ForecastTable dt = TimeSeries.weightedMovingAverage(GetInput(), 5, (Decimal)0.05, (Decimal)0.15, (Decimal)0.8);
            grdResults.DataSource = dt;

            updateMeasurements(dt);
            updateGraph(dt);
        }

        private void eSToolStripMenuItem_Click(object sender, EventArgs e)
        {
            grdResults.Columns.Clear();
            ForecastTable dt = TimeSeries.exponentialSmoothing(GetInput(), 5, (Decimal)0.8);
            grdResults.DataSource = dt;

            updateMeasurements(dt);
            updateGraph(dt);
        }

        private void aRSToolStripMenuItem_Click(object sender, EventArgs e)
        {
            grdResults.Columns.Clear();

            ForecastTable dt = TimeSeries.adaptiveRateSmoothing(GetInput(), 5, (Decimal)0.2, (Decimal)0.8);
            grdResults.DataSource = dt;

            updateMeasurements(dt);
            updateGraph(dt);
        }


        private void cSVFormatToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // show file selection dialog
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                StreamReader reader = null;
                // read maximum 50 points
                double[] tempData = new double[50];

                try
                {
                    // open selected file
                    reader = File.OpenText(openFileDialog.FileName);
                    string str = null;
                    int i = 0;

                    // read the data
                    while ((i < 50) && ((str = reader.ReadLine()) != null))
                    {
                        // parse the value
                        tempData[i] = double.Parse(str);

                        i++;
                    }

                    // allocate and set data
                    data = new double[i];
                    dataToShow = new double[i, 2];
                    Array.Copy(tempData, 0, data, 0, i);
                    for (int j = 0; j < i; j++)
                    {
                        dataToShow[j, 0] = j;
                        dataToShow[j, 1] = data[j];
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("Failed reading the file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                finally
                {
                    // close file
                    if (reader != null)
                        reader.Close();
                }

                // Populate the DataGriview
                grdResults.ColumnCount = 2;
                grdResults.Columns[0].Name = "ID";
                grdResults.Columns[1].Name = "Real";

                for (int j = 0; j < data.Length; j++)
                {
                    string[] row = new string[] { j.ToString(), data[j].ToString() };
                    grdResults.Rows.Add(row);
                }

                // Populate the Data Graph
                // This is to remove all plots
                zedPreditionGraph.GraphPane.CurveList.Clear();

                // GraphPane object holds one or more Curve objects (or plots)
                GraphPane myPane = zedPreditionGraph.GraphPane;
                double x, y1;
                PointPairList list1 = new PointPairList();

                for (int i = 0; i < data.Length; i++)
                {
                    x = Convert.ToDouble(grdResults.Rows[i].Cells["ID"].FormattedValue.ToString());
                    y1 = Convert.ToDouble(grdResults.Rows[i].Cells["Real"].FormattedValue.ToString());
                    list1.Add(x, y1);
                }
                // Add cruves to myPane object
                LineItem myCurve1 = myPane.AddCurve("Real Data", list1, Color.Blue, SymbolType.Diamond);

                myCurve1.Line.Width = 2.0F;
                myPane.Title.Text = "Time Series Predition";
                myPane.XAxis.Title.Text = "Time";
                myPane.YAxis.Title.Text = "Value";

                // I add all three functions just to be sure it refeshes the plot.   
                zedPreditionGraph.AxisChange();
                zedPreditionGraph.Invalidate();
                zedPreditionGraph.Refresh();
            }
        }

    }
}
